package com.gitee.wsl.ext.okio.base

import okio.IOException

/**
 * The states that represent the progress of an HTTP call.
 *
 * @see OkHttpClient.callWithCounting
 */
sealed class CallState<out T> {
    /**
     * An intermediate state indicating that the HTTP request body is being sent.
     *
     * This state is not emitted if the `countUpload` parameter is `false` or the `request` has no body.
     *
     * @property bytesTransferred The number of bytes that have been sent as the request body so far.
     * @property bytesTotal The length of the request body specified in the `Content-Length` header.
     * @see progressPercentage
     */
    class Uploading(override val bytesTransferred: Long, override val bytesTotal: Long) :
        CallState<Nothing>(), TransferProgress

    /**
     * An intermediate state indicating that the HTTP response body is being received.
     *
     * This state is not emitted if the `countDownload` parameter is `false` or the response status
     * code is other than `2xx`.
     *
     * @property bytesTransferred The number of bytes that have been sent as the response body so far.
     * If the `handlePartialResponse` parameter is `true` and the response is a single-part
     * `206 Partial Content` response, this value includes the start offset of the `Content-Range` header.
     * @property bytesTotal If the `handlePartialResponse` parameter is `true` and the response is
     * a single-part `206 Partial Content` response, this value is the total length of the
     * `Content-Range` header. Otherwise, this is the length of the response body specified in the
     * `Content-Length` header.
     * @see progressPercentage
     */
    class Downloading(override val bytesTransferred: Long, override val bytesTotal: Long) :
        CallState<Nothing>(), TransferProgress

    /**
     * A final state indicating that the HTTP call completed successfully.
     * After emitting this state, the `flow` completes normally.
     *
     * @property data The result returned by the `responseHandler`.
     * @property bytesUploaded The number of bytes finally sent as the request body,
     * or `-1` if the `countUpload` parameter is `false` or the `request` has no body.
     * @property bytesDownloaded The number of bytes finally received as the response body, unless
     * the `countDownload` parameter is `false` or the response status code is other than `2xx`.
     * If the `handlePartialResponse` parameter is `true` and the response is a single-part
     * `206 Partial Content` response, this value includes the start offset of the `Content-Range` header.
     * If the `handlePartialResponse` parameter is `true` and the response is `416 Range Not Satisfiable`,
     * this value is the total length of the `Content-Range` header.
     * If neither of them, this value is `-1`.
     */
    class Success<T>(val data: T, val bytesUploaded: Long, val bytesDownloaded: Long) :
        CallState<T>()

    /**
     * A final state indicating that the HTTP call failed with an [IOException].
     * After emitting this state, the `flow` completes normally.
     *
     * This state is also emitted when the `responseHandler` throws an [IOException].
     *
     * @property exception the [IOException] that caused the failure.
     */
    class Failure(val exception: IOException) : CallState<Nothing>()
}